package org.xiaohanghu.starter;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.xiaohanghu.starter.net.ClassPathUrlConvertor;
import org.xiaohanghu.starter.net.HomeUrlConvertor;
import org.xiaohanghu.starter.net.UrlFactory;


/**
 * @author xiaohanghu
 */
public class StartConfig {

	private int logLever = Logger.LEVEL_ERROR;

	// private String homePath;
	// private String currentPath;
	private URI homeUri;
	private URI currentUri;

	private UrlFactory urlFactory = new UrlFactory();

	private JavaResources javaResources = new JavaResources();

	private List<String> jvmOptions = new ArrayList<String>();

	private Map<String, String> systemProperties = new HashMap<String, String>();

	private String mainClass;

	private List<String> arguments = new ArrayList<String>();

	public StartConfig() throws URISyntaxException {
		this(null, null);
	}

	public StartConfig(URL home, URL currentUrl) throws URISyntaxException {
		if (null != home) {
			this.homeUri = home.toURI();
		}
		if (null != currentUrl) {
			this.currentUri = currentUrl.toURI();
		}
		addUrlConvertor();
	}

	protected void addUrlConvertor() {
		if (null != homeUri) {
			HomeUrlConvertor homeUrlConvertor = new HomeUrlConvertor(homeUri);
			urlFactory.addUrlConvertor(HomeUrlConvertor.URI_SCHEME,
					homeUrlConvertor);
			urlFactory.setDefaultScheme(HomeUrlConvertor.URI_SCHEME);
		} else {
			urlFactory.setDefaultScheme(ClassPathUrlConvertor.URI_SCHEME);
		}
		ClassPathUrlConvertor classPathUrlConvertor = new ClassPathUrlConvertor();
		urlFactory.addUrlConvertor(ClassPathUrlConvertor.URI_SCHEME,
				classPathUrlConvertor);

	}

	public int getLogLever() {
		return logLever;
	}

	public void setLogLever(String logLevel) {
		if (StringUtils.isBlank(logLevel)) {
			return;
		}
		this.logLever = Logger.getLevel(logLevel);
	}

	public Set<URL> getJavaResourcesUrls() {
		return javaResources.getResources();
	}

	public void setJavaResources(JavaResources javaResources) {
		this.javaResources = javaResources;
	}

	public JavaResources getJavaResources() {
		return javaResources;
	}

	public void addJarResource(String path) throws URISyntaxException,
			MalformedURLException {
		URL url = urlFactory.toUrl(path, currentUri);
		javaResources.addJarResource(url);
	}

	public void addJarResources(String jarUrls) throws MalformedURLException,
			URISyntaxException {
		List<URL> urls = urlFactory.toUrls(jarUrls, currentUri);
		javaResources.addJarResource(urls);
	}

	public void addClassesResource(String uri) throws MalformedURLException,
			URISyntaxException {
		uri = PathUtils.getReallPath(uri);
		if (!uri.endsWith("/")) {
			uri += "/";
		}
		URL url = urlFactory.toUrl(uri, currentUri);
		if (null == url) {
			return;
		}
		javaResources.addClassesResource(url);
	}

	public void addClassesResources(String classesUris)
			throws MalformedURLException, URISyntaxException {
		List<URL> urls = new ArrayList<URL>();
		classesUris = StringUtils.trimToNull(classesUris);
		if (null == classesUris) {
			return;
		}
		String[] strs = classesUris.split(",");
		for (String str : strs) {
			addClassesResource(str);
		}
		javaResources.addClassesResource(urls);
	}

	public void addJvmOption(String option) {
		if (StringUtils.isNotBlank(option)) {
			this.jvmOptions.add(option);
		}
	}

	public void addJvmOptions(String configFilePath)
			throws MalformedURLException, URISyntaxException {
		configFilePath = StringUtils.trimToNull(configFilePath);
		if (null == configFilePath) {
			return;
		}
		URL url = urlFactory.toUrl(configFilePath, currentUri);
		try {
			URLConnection urlConnection = url.openConnection();
			InputStream inputStream = urlConnection.getInputStream();
			Reader reader = IOUtils.createrResder(inputStream, "utf-8");
			List<String> strs = IOUtils.readBySeparator(reader);
			this.jvmOptions.addAll(strs);
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}

	public void addSystemProperties(String configFilePath)
			throws MalformedURLException, URISyntaxException {
		configFilePath = StringUtils.trimToNull(configFilePath);
		if (null == configFilePath) {
			return;
		}
		URL url = urlFactory.toUrl(configFilePath, currentUri);
		addSystemProperties(url);
	}

	public void addSystemProperties(URL url) {
		try {
			Properties properties = PropertiesUtils.loadProperties(url);
			PropertiesUtils.addAllProperties(this.systemProperties, properties);
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}

	public void addSystemProperties(Properties properties) {
		PropertiesUtils.addAllProperties(this.systemProperties, properties);
	}

	public void addSystemProperties(Map<String, String> properties) {
		this.systemProperties.putAll(properties);
	}

	public void addSystemProperty(String key, String value) {
		if (StringUtils.isNotBlank(key)) {
			this.systemProperties.put(key, value);
		}
	}

	public List<String> getJvmOptions() {
		return jvmOptions;
	}

	public void setJvmOptions(List<String> jvmOptions) {
		this.jvmOptions = jvmOptions;
	}

	public Map<String, String> getSystemProperties() {
		return systemProperties;
	}

	public String getMainClass() {
		return mainClass;
	}

	public void setMainClass(String mainClass) {
		this.mainClass = mainClass;
	}

	public List<String> getArguments() {
		return arguments;
	}

	public void addArgument(String argument) {
		this.arguments.add(argument);
	}

	public void addArguments(String... arguments) {
		for (String argument : arguments) {
			this.addArgument(argument);
		}
	}

}
